<template>
  <div class="qr-code" v-loading="loading" :style="{width:`${width}px`,height:`${height}px`,padding:`${padding}px`}">
    <div class="qr-error login-tips" v-if="!hasLogin">
      <el-button size="small" type="primary" @click="$emit('login')">请先登录</el-button>
    </div>
    <div class="code-box"
      v-show="hasLogin">
      <div
        ref="qrCode"
        key="code">
      </div>
      <div v-show="error"
        class="refresh qr-error"
        key="refresh"
        @click="refreshCode">
        <div v-if="error">
          <svg-icon icon-class="code-refresh" />
          <p class="text-error">{{error}}</p>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import QRCode from 'qrcodejs2'
import { createOrderApi, getOrderInfoApi, checkOrderInfo } from './api'
import { getQueryString, debounce } from '@/utils'
export default {
  name: 'LyPaymentCode',
  props: {
    isShow: {
      type: Boolean,
      default: true
    },
    hasLogin: {
      type: Boolean,
      default: false
    },
    product: {
      type: Object,
      require: true
    },
    otherParamsStr: {
      type: String,
      default: '{}'
    },
    width: {
      type: Number,
      default: 150
    },
    height: {
      type: Number,
      default: 150
    },
    padding: {
      type: Number,
      default: 10
    },
    openPos: {
      type: String,
      default: 'XZMainWindow'
    }
  },
  data () {
    return {
      loading: false,
      qrcode: null,
      timer: null,
      error: '',
      invalidTime: null
    }
  },
  watch: {
    'product.id': {
      handler () {
        if (this.createOrder_) {
          this.createOrder_()
        } else {
          this.createOrder()
        }
      },
      immediate: true
    },
    otherParamsStr () {
      this.createOrder_()
    },
    'isShow' () {
      this.createOrder_()
    },
    'hasLogin' () {
      this.createOrder_()
    }
  },
  created () {
    this.getLyPayConfig()
    this.createOrder_ = debounce(() => {
      this.createOrder()
    }, 250, false)
  },
  mounted () {
    const container = this.$refs.qrCode
    this.qrcode = new QRCode(container, {
      text: this.text,
      width: this.width - this.padding * 2,
      height: this.height - this.padding * 2,
      colorDark: '#000000',
      colorLight: '#ffffff',
      correctLevel: 0
    })
    this.$xzReg('xz_lx_pay_res', (res) => {
      this.dealPayRes(JSON.parse(res).data)
    })
  },
  activated () {
    this.createOrder()
  },
  deactivated () {
    clearTimeout(this.timer)
  },
  beforeDestroy () {
    clearTimeout(this.timer)
  },

  methods: {
    getLyPayConfig () {
      this.$xzAsy('xz_lygetpayconfig').then(res => {
        this.payConfig = res
      })
    },
    refreshCode () {
      this.$emit('refresh')
      this.clearOrder()
      this.createOrder()
    },
    setTime (oldCode) {
      clearTimeout(this.timer)
      if (this.invalidTime < Date.now()) {
        this.error = '二维码已过期'
        this.emitOrderStatus('timeout')
        return
      }
      this.timer = setTimeout(() => {
        if (this.error || oldCode !== this.product.orderid) return
        oldCode = this.product.orderid
        checkOrderInfo({ orderid: this.product.orderid, sign: this.product.sign, type: 'lenovo' }).then(res => {
          if (oldCode !== this.product.orderid) return
          const data = res.data || {}
          if (data.status === 0) {
            this.emitOrderStatus('succes')
          } else if (data.status === 2) {
            this.error = '订单无效！'
            this.emitOrderStatus('error')
          }
          this.setTime(oldCode)
        }).catch(() => {
          this.setTime(oldCode)
        })
      }, 3000)
    },
    async createOrder () {
      clearTimeout(this.timer)
      if ([!this.hasLogin, !this.product.id].includes(true)) return
      if (this.product.orderid && this.product.otherParamsStr === this.otherParamsStr) {
        const payURL = this.product.payURL
        const invalidTime = getQueryString(payURL, 'invalidTime')
        if (invalidTime > Date.now()) {
          this.makePayCode()
          return
        }
      }
      const params = {
        product_id: [this.product.id],
        pay_way: 5,
        pay_entry: 'web',
        channel_id: this.$store.getters.appInfo.channel
      }
      const otherParamsStr = this.otherParamsStr
      this.otherParamsStrCache = otherParamsStr
      const otherParams = JSON.parse(otherParamsStr)
      if (otherParams.noproduct) {
        params.product_id = []
      }
      if (otherParams.couponid) {
        params.coupon_id = otherParams.couponid
      }
      if (otherParams.actids) {
        const ids = otherParams.actids.split(',')
        params.act_ids = ids.map(id => parseInt(id))
      }
      if (otherParams.giveproduct) {
        params.give_product = otherParams.giveproduct
      }
      if (otherParams.addproduct) {
        params.add_product_id = otherParams.addproduct
      }
      if (otherParams.quantity) {
        params.quantity = parseInt(otherParams.quantity)
        params.act_fixed_id = otherParams.act_fixed_id
      }
      this.loading = true
      createOrderApi(params).then(res => {
        this.oldId = params.product_id[0] || this.product.id
        if (this.product.id !== this.oldId) {
          this.loading = false
          return
        }
        this.orderInfo = res.data || {}
        this.getOrderInfo()
      }).catch(() => {
        this.setCodeError()
      })
    },
    dealPayRes (res) {
      this.loading = false
      // if (this.product.id !== this.oldId) {
      //   return
      // }

      this.error = ''
      this.product.payURL = res.tradeUrl
      this.product.orderid = this.orderInfo.order_id
      this.product.sign = this.orderInfo.sign
      this.product.otherParamsStr = this.otherParamsStrCache
      this.makePayCode()
    },
    getOrderInfo () {
      if (!this.orderInfo.order_id) {
        this.setCodeError()
        return
      }
      const obj = {
        22: '1049886401363328',
        108: '970085254654081',
        111: '1217415275010944'
      }
      const appid = this.$store.getters.appInfo.appID
      // this.$xzAsy('xz_get_merchant_token').then(res => {
      const orderInfo = {
        type: this.orderInfo.pay_way_str,
        orderid: this.orderInfo.order_id,
        sign: this.orderInfo.sign,
        title: this.orderInfo.title,
        appID: process.env.VUE_APP_ID
      }
      const payAppId = obj[appid]
      if (payAppId) {
        orderInfo.payAppId = payAppId
      }
      if (this.payConfig) {
        Object.assign(orderInfo, {
          trade_method: 'APP',
          payAppId: this.payConfig.appId,
          deviceId: this.payConfig.deviceId
        })
      }
      getOrderInfoApi(orderInfo).then(res => {
        if (this.product.id !== this.oldId) {
          this.loading = false
          return
        }
        this.error = ''
        this.setCodeInfo(res.data)
      }).catch(() => {
        this.setCodeError()
      })
    },
    setCodeInfo (data) {
      if (data.prepayInfo.param) {
        const params = JSON.parse(data.prepayInfo.param)
        params.productCode = 'COLLECT_CODE'

        params.deviceId = this.payConfig.deviceId
        // pay结果在 dealPayRes 中处理
        this.$xzAsy('xz_lysdk_pay', JSON.stringify(params), this.openPos)
        return
      }
      this.loading = false
      this.product.payURL = data.payURL
      this.product.orderid = this.orderInfo.order_id
      this.product.sign = this.orderInfo.sign
      this.product.otherParamsStr = this.otherParamsStrCache
      this.makePayCode()
    },
    setCodeError () {
      this.error = '请刷新二维码'
      this.loading = false
    },
    makePayCode () {
      const payURL = this.product.payURL
      this.invalidTime = getQueryString(payURL, 'invalidTime')
      if (this.qrcode) {
        this.qrcode.makeCode(payURL)
        this.qrcode._el.title = ''
        this.setTime(this.product.orderid)
      }
    },
    clearOrder () {
      this.product.payURL = null
      this.product.orderid = null
      this.product.sign = null
      this.product.otherParamsStr = null
    },
    emitOrderStatus (status) {
      this.clearOrder()
      this.$emit('onStatusChange', status)
    }
  }
}
</script>
<style lang="scss" scoped>
@import "./index.scss";
</style>
